package com.ruoyi.api.api;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisException;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.commons.io.IOUtils;
import redis.clients.jedis.util.Pool;

import java.io.IOException;
import java.io.InputStream;

public class RedisStockService {

    private static final Logger logger = LoggerFactory.getLogger(RedisStockService.class);
    private final String redisHost;
    private final int redisPort;
    private final String redisPassword;
    private final int redisDbIndex;
    private Pool<Jedis> jedisPool;
    private final String stockKey = "products_data_stock";
    private String deductScript;
    private String addScript;
    private static final String SUCCESS = "1";

    // 构造函数，接收密码和数据库索引
    public RedisStockService(String redisHost, int redisPort, String redisPassword, int redisDbIndex) {
        this.redisHost = redisHost;
        this.redisPort = redisPort;
        this.redisPassword = redisPassword;
        this.redisDbIndex = redisDbIndex;
        initJedisPool();
        loadScripts();
    }

    // 没有密码的构造函数，方便测试
    public RedisStockService(String redisHost, int redisPort, int redisDbIndex) {
        this(redisHost, redisPort, null, redisDbIndex);
    }

    public RedisStockService(String redisHost, int redisPort) {
        this(redisHost, redisPort, "123456", 0); // 默认使用数据库索引为 0
    }

    private void initJedisPool() {
        GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxTotal(100);
        poolConfig.setMaxIdle(10);
        poolConfig.setMinIdle(5);

        int timeout = 2000; // 连接超时设置
        try {
            if (redisPassword != null && !redisPassword.isEmpty()) {
                // 指定密码和数据库索引
                jedisPool = new JedisPool(poolConfig, redisHost, redisPort, timeout, redisPassword, redisDbIndex);
            } else {
                // 只指定数据库索引
                jedisPool = new JedisPool(poolConfig, redisHost, redisPort, timeout, null, redisDbIndex);
            }
        } catch (Exception e) {
            logger.error("初始化 JedisPool 失败", e);
            throw new RuntimeException("初始化 JedisPool 失败", e);
        }
    }

    private void loadScripts() {
        try (InputStream deductStream = getClass().getClassLoader().getResourceAsStream("deduct_stock.lua");
             InputStream addStream = getClass().getClassLoader().getResourceAsStream("add_stock.lua")) {

            if (deductStream == null) {
                throw new RuntimeException("找不到 deduct_stock.lua 脚本文件");
            }
            if (addStream == null) {
                throw new RuntimeException("找不到 add_stock.lua 脚本文件");
            }

            deductScript = IOUtils.toString(deductStream, "UTF-8");
            addScript = IOUtils.toString(addStream, "UTF-8");

            logger.info("成功加载库存操作脚本");
        } catch (IOException e) {
            throw new RuntimeException("加载脚本失败", e);
        }
    }

    public void initStock(String productId, int initialStock) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hset(stockKey, productId, String.valueOf(initialStock));
            logger.info("初始化库存, productId: {}, initialStock: {}", productId, initialStock);
        } catch (JedisException e) {
            logger.error("初始化库存失败, productId: {}", productId, e);
            throw new RuntimeException("初始化库存失败", e);
        }
    }

    // 使用 Lua 脚本扣减库存
    public boolean deductStock(String productId, int quantity) {
        if (quantity <= 0) {
            logger.warn("扣减数量必须为正整数，productId：{}，quantity：{}", productId, quantity);
            return false;
        }

        try (Jedis jedis = jedisPool.getResource()) {
            logger.info("尝试扣减库存，productId：{}，quantity：{}", productId, quantity);
            Object result = jedis.eval(deductScript, 1, stockKey, productId, String.valueOf(quantity));

            boolean success = SUCCESS.equals(result.toString());
            if (success) {
                logger.info("扣减库存成功，productId：{}，数量：{}", productId, quantity);
            } else {
                logger.warn("扣减库存失败，productId：{}，数量：{}", productId, quantity);
            }
            return success;
        } catch (JedisException e) {
            logger.error("扣减库存异常，productId：{}，异常：{}", productId, e.getMessage(), e);
            return false;
        }
    }

    public boolean addStock(String productId, int quantity) {
        if (quantity <= 0) {
            logger.warn("恢复数量必须为正整数，productId：{}，quantity：{}", productId, quantity);
            return false;
        }

        try (Jedis jedis = jedisPool.getResource()) {
            // 假设 stockKey 为 "products_data_stock"（与你的存储格式一致）
            String hashKey = stockKey; // 即 PRODUCT_DATA + "_stock"
            String field = productId; // 商品ID（字符串）
            String script =
                    "local hashKey = KEYS[1] " +
                            "local field = ARGV[1] " +
                            "local increment = tonumber(ARGV[2]) " +
                            "redis.call('HINCRBY', hashKey, field, increment) " +
                            "return 1"; // 简化版脚本，直接执行 HINCRBY

            Object result = jedis.eval(script, 1, hashKey, field, String.valueOf(quantity));
            boolean success = "1".equals(result.toString());

            if (success) {
                logger.info("恢复库存成功，productId：{}，数量：{}", productId, quantity);
            } else {
                logger.warn("恢复库存失败，productId：{}，数量：{}", productId, quantity);
            }
            return success;
        } catch (JedisException e) {
            logger.error("恢复库存异常，productId：{}，异常：{}", productId, e.getMessage(), e);
            return false;
        }
    }

    // 获取库存
    public int getStock(String productId) {
        try (Jedis jedis = jedisPool.getResource()) {
            String stockStr = jedis.hget(stockKey, productId);
            return stockStr != null ? Integer.parseInt(stockStr) : 0;
        } catch (Exception e) {
            logger.error("获取库存失败，productId：{}", productId, e);
            return -1;
        }
    }

    public void close() {
        if (jedisPool != null) {
            jedisPool.close();
            logger.info("JedisPool 关闭");
        }
    }
    // RedisStockService 新增方法：直接调用 HINCRBY
    /**
     * 恢复商品库存
     * @param stockKey Redis中存储库存的哈希键名
     * @param productId 商品ID（哈希字段名）
     * @param quantity 要恢复的数量（正数）
     * @return 恢复成功返回true，失败返回false
     */
    public boolean hincrByStock(String stockKey, String productId, int quantity) {
        if (quantity <= 0) {
            logger.warn("无效恢复数量，productId={}, quantity={}", productId, quantity);
            return false;
        }

        try (Jedis jedis = jedisPool.getResource()) {
            // 执行 HINCRBY 命令，返回新的库存值
            Long newStock = jedis.hincrBy(stockKey, productId, quantity);
            if (newStock != null) {
                logger.info("恢复库存成功，stockKey={}, productId={}, 数量={}, 新库存={}",
                        stockKey, productId, quantity, newStock);
                System.out.println("恢复数据量成功============================================");
                return true;
            }
            logger.warn("恢复库存失败，stockKey={}, productId={}, 数量={}", stockKey, productId, quantity);
            return false;
        } catch (JedisException e) {
            logger.error("HINCRBY 异常，stockKey={}, productId={}, 错误={}",
                    stockKey, productId, e.getMessage());
            return false;
        }
    }
    public static void main(String[] args) {
        // 修改这里，传入正确的密码和数据库索引
        RedisStockService service = new RedisStockService("localhost", 6379, "123456", 15);

        // 初始化库存（90件）
        service.initStock("2", 90);
        System.out.println("初始化库存: 90");

        // 扣减 10 件库存
        boolean success = service.deductStock("2", 10);
        System.out.println("扣减10件结果: " + (success ? "成功" : "失败"));
        System.out.println("当前库存: " + service.getStock("2"));

        // 增加 5 件库存
        success = service.addStock("2", 5);
        System.out.println("恢复5件结果: " + (success ? "成功" : "失败"));
        System.out.println("当前库存: " + service.getStock("2"));

        // 尝试恢复不存在的商品库存
        success = service.addStock("999", 10);
        System.out.println("恢复不存在商品结果: " + (success ? "成功" : "失败"));

        service.close();
    }
}
